#ifndef CONNECTION
#define CONNECTION

// 这里是服务器的核心，服务器的工作就是处理各种连接

/**
 * 对连接的全方位的管理，对通信连接的所有操作都是通过这个模块提供的功能完成
 * 数据应该由用户处理，所以必须要有业务处理回调函数
 * 一个连接建立成功后，该如何处理，有用户决定，因此必须有连接建立成功的回调函数
 * 连接关闭前的回调函数
 * 任意事件的回调函数
 * 管理：
 * 1.套接字管理
 * 2.连接事件的管理
 * 3.缓冲区管理，便于套接字数据的接受和发送
 * 4.上下文管理，有时独到的数据不一定完整，需要得到完整的数据再处理
 * 5.回调函数的管理
 *
 * 功能：
 * 1.发送数据：提供的发送数据的接口，只是发送到缓冲区里，不是真正的发送
 * 2.关闭连接：和1一样，在实际释放连接之前，检查缓冲区是否为空，并不直接关闭连接
 * 3.启动非活跃连接的超时销毁功能
 * 4.取消非活跃连接的超时销毁功能
 * 5.协议切换：不同协议对应的数据不同，如何进行业务处理，取决于上下文，以及数据的业务处理函数
 */

#include "Any.hpp"
#include "Buffer.h"
#include "Socket.h"
#include "Channel.h"
#include <memory>
#include <functional>

enum class ConnStatu
{
    DISCONNECTED,
    DISCONNECTING,
    CONNECTING,
    CONNECTED
};

class Connection;
using PtrConnection = std::shared_ptr<Connection>;

class Connection : public std::enable_shared_from_this<Connection>
{
private:
    using ConnectedCallBack = std::function<void(const PtrConnection &)>;
    using MessageCallBack = std::function<void(const PtrConnection &, Buffer *)>;
    using RandomEventCallBack = std::function<void(const PtrConnection &)>;
    using ClosedCallBack = std::function<void(const PtrConnection &)>;

private:
    // 五个Channel的事件回调函数
    void HandleRead();
    void HandleWrite();
    void HandleClose();
    void HandleError();
    void HandleRandom();

    // 连接获取之后，所处的状态下要进行各种设置，给Channel设置事件回调，启动读监控
    void EstablishedInLoop();
    // 实际释放连接的接口
    void ReleaseInLoop();
    // 把数据放在缓冲区内，启动读事件监控
    void SendInLoop(const char *, uint32_t);
    // 根据是否缓冲区内还存在数据决定关闭
    void ShutDownInLoop();
    // 启用/停止等待非活跃链接，参数为等待的秒数
    void EnableInactiveReleaseInLoop(uint64_t);
    void DisableInactiveReleaseInLoop();
    // 切换协议，重置上下文以及阶段性处理函数
    void UpgradeInLoop(const Any &,
                       const ConnectedCallBack &,
                       const RandomEventCallBack &,
                       const ClosedCallBack &,
                       const MessageCallBack &);

public:
    Connection(EventLoop *loop, uint64_t conn_id, int sockfd);
    ~Connection();

public:
    int getFd();
    uint64_t getId();
    bool getConnected();
    void SetContext(const Any &);
    Any *getContext();
    // 连接获取之后，所处的状态下要进行各种设置，给Channel设置事件回调，启动读监控
    void Established();
    // 把数据放在缓冲区内，启动读事件监控
    void Send(const char *, uint32_t);
    // 根据是否缓冲区内还存在数据决定关闭
    void ShutDown();
    // 启用/停止等待非活跃链接，参数为等待的秒数
    void EnableInactiveRelease(uint64_t);
    void DisableInactiveRelease();
    // 切换协议，重置上下文以及阶段性处理函数
    void Upgrade(const Any &, const ConnectedCallBack &, const RandomEventCallBack &, const ClosedCallBack &, const MessageCallBack &);

    void Release();
    void SetConnectedCallBack(const ConnectedCallBack &);
    void SetMessageCallBack(const MessageCallBack &);
    void SetRandomEventCallBack(const RandomEventCallBack &);
    void SetClosedCallBack(const ClosedCallBack &);
    void SetServerClosedCallBack(const ClosedCallBack &cl_cb);

private:
    uint64_t _conn_id;                     // 连接的唯一id
    int _sockfd;                           // 连接关联的fd
    bool _enable_inactive_release = false; // 连接是否启动非活跃销毁
    ConnStatu _statu;                      // 连接状态
    Socket _socket;                        // 套接字操作管理
    Channel _channel;                      // 连接的事件管理
    Buffer _in_buffer;                     // 读缓冲器，从套接字中读到的数据存放在这里
    Buffer _out_buffer;                    // 写缓冲区，数据处理完成后待发送的数据放在这里
    Any _context;                          // 连接上下文的管理
    EventLoop *_loop;                      // 连接所关联的一个eventloop
    // 这四个是服务器组件使用者来设置的
    ConnectedCallBack _conn_cb;      // 建立连接回调
    RandomEventCallBack _rand_ev_cb; // 任意事件的回调
    ClosedCallBack _close_cb;        // 连接关闭的回调
    MessageCallBack _mess_cb;        // 数据处理回调
    // 这个是组件内部设置的，服务器要管理所有的连接，某个连接断开了，服务器也必须是断开的，否则只有
    // 使用者自己断开了，管理就混乱了
    ClosedCallBack _server_close_cb; // 服务器内部连接关闭的回调
};

#endif